#include "TurnLampNormalState.h"
#include "LampManager.h"
#include "F3LampInterfaces.h"
#include "Animations.h"
#include "FrntTurnLampSnapshot.h"
#include "F3LampInterfaces.h"
#include <string.h>

NormalStateMachine g_NormalStateMachine;

void InitNormalStateMachine(void)
{
    g_NormalStateMachine.sm_.Entry = NormalModeEntry;
    g_NormalStateMachine.sm_.Excute = NormalModeExcute;
    g_NormalStateMachine.sm_.Exit = NormalModeExit;
    g_NormalStateMachine.sm_.waitExitCount_ = 3;

    g_NormalStateMachine.defaultMode_.sm_.Entry = NormalStateMachineDefaultEntry;
    g_NormalStateMachine.defaultMode_.sm_.Excute = NormalStateMachineDefaultExcute;
    g_NormalStateMachine.defaultMode_.sm_.Exit = NormalStateMachineDefaultExit;
    g_NormalStateMachine.defaultMode_.sm_.waitExitCount_ = 3;

    g_NormalStateMachine.leFrntTurnLampFlicker_.sm_.Entry = NormalStateMachineLeFrntTurnLampFlickerEntry;
    g_NormalStateMachine.leFrntTurnLampFlicker_.sm_.Excute = NormalStateMachineLeFrntTurnLampFlickerExcute;
    g_NormalStateMachine.leFrntTurnLampFlicker_.sm_.Exit = NormalStateMachineLeFrntTurnLampFlickerExit;
    g_NormalStateMachine.leFrntTurnLampFlicker_.sm_.waitExitCount_ = 3;

    g_NormalStateMachine.leFrntTurnLampFlow_.sm_.Entry = NormalStateMachineLeFrntTurnLampFlowEntry;
    g_NormalStateMachine.leFrntTurnLampFlow_.sm_.Excute = NormalStateMachineLeFrntTurnLampFlowExcute;
    g_NormalStateMachine.leFrntTurnLampFlow_.sm_.Exit = NormalStateMachineLeFrntTurnLampFlowExit;
    g_NormalStateMachine.leFrntTurnLampFlow_.sm_.waitExitCount_ = 3;

    g_NormalStateMachine.dayTimeMode_.sm_.Entry = NormalStateMachineDayTimeModeEntry;
    g_NormalStateMachine.dayTimeMode_.sm_.Excute = NormalStateMachineDayTimeModeExcute;
    g_NormalStateMachine.dayTimeMode_.sm_.Exit = NormalStateMachineDayTimeModeExit;
    g_NormalStateMachine.dayTimeMode_.sm_.waitExitCount_ = 3;

    g_NormalStateMachine.posnMode_.sm_.Entry = NormalStateMachinePosnModeEntry;
    g_NormalStateMachine.posnMode_.sm_.Excute = NormalStateMachinePosnModeExcute;
    g_NormalStateMachine.posnMode_.sm_.Exit = NormalStateMachinePosnModeExit;
    g_NormalStateMachine.posnMode_.sm_.waitExitCount_ = 3;
}

static void SelectExitLogic(NormalStateMachine* normalStateMachine, NormalState lastState, NormalState newState)
{
    switch(lastState)
    {
        case NormalStateLeFrntTurnLamp_Flicker:
        {
            resetWaitExitCount(&normalStateMachine->leFrntTurnLampFlicker_.sm_, 3);//wait 3  periods
            normalStateMachine->leFrntTurnLampFlicker_.sm_.Exit();
            break;
        }

        case NormalStateLeFrntTurnLamp_Flow:
        {
            resetWaitExitCount(&normalStateMachine->leFrntTurnLampFlow_.sm_, 3);//wait 3  periods
            normalStateMachine->leFrntTurnLampFlow_.sm_.Exit();
            break;
        }

        case NormalStateLeFrntTurnLamp_DayTime:
        {
            resetWaitExitCount(&normalStateMachine->dayTimeMode_.sm_, 3);//wait 3  periods
            normalStateMachine->dayTimeMode_.sm_.Exit();
            break;
        }

        case NormalStateLeFrntTurnLamp_Posn:
        {
            resetWaitExitCount(&normalStateMachine->posnMode_.sm_, 3);//wait 3  periods
            normalStateMachine->posnMode_.sm_.Exit();
            break;
        }


        case NormalStateLeFrntTurnLamp_DayTimeAndPosBoth_ButDayTime:
        {
            if(newState == NormalStateLeFrntTurnLamp_Flicker || newState == NormalStateLeFrntTurnLamp_Flow)
            {
                resetWaitExitCount(&normalStateMachine->dayTimeMode_.sm_, 3);//wait 3  periods
                normalStateMachine->dayTimeMode_.sm_.Exit();
            }
            break;
        }
        case NormalStateLeFrntTurnLamp_DayTimeAndPosBoth_ButPosn:
        {
            if(newState == NormalStateLeFrntTurnLamp_Flicker || newState == NormalStateLeFrntTurnLamp_Flow)
            {
                resetWaitExitCount(&normalStateMachine->posnMode_.sm_, 3);//wait 3  periods
                normalStateMachine->posnMode_.sm_.Exit();
            }
            break;
        }

        default:
        {
            resetWaitExitCount(&normalStateMachine->defaultMode_.sm_, 3);//wait 3  periods
            normalStateMachine->defaultMode_.sm_.Exit();
            break;
        }
    }
}

static void SelectEntryLogic(NormalStateMachine* normalStateMachine, NormalState newState)
{
    switch(newState)
    {
        case NormalStateLeFrntTurnLamp_Flicker:
        {
            normalStateMachine->leFrntTurnLampFlicker_.sm_.Entry();
            break;
        }

        case NormalStateLeFrntTurnLamp_Flow:
        {
            normalStateMachine->leFrntTurnLampFlow_.sm_.Entry();
            break;
        }

        case NormalStateLeFrntTurnLamp_DayTime:
        case NormalStateLeFrntTurnLamp_DayTimeAndPosBoth_ButDayTime:
        {
            if(NormalStateLeFrntTurnLamp_DayTimeAndPosBoth_ButDayTime != g_TurnLastState.normalState_)
            {
                normalStateMachine->dayTimeMode_.sm_.Entry();
            }
            break;
        }

        case NormalStateLeFrntTurnLamp_Posn:
        case NormalStateLeFrntTurnLamp_DayTimeAndPosBoth_ButPosn:
        {
            if(NormalStateLeFrntTurnLamp_DayTimeAndPosBoth_ButPosn != g_TurnLastState.normalState_)
            {
                normalStateMachine->posnMode_.sm_.Entry();
            }
            break;
        }

        default:
        {
            normalStateMachine->defaultMode_.sm_.Entry();
            break;
        }
    }
}

static void NormalStateMachineEntryLogic(NormalStateMachine* normalStateMachine, NormalState lastState, NormalState newState)
{
    if(lastState != newState)
    {
        switch (lastState)
        {
            case NormalStateLeFrntTurnLamp_Flicker:
            case NormalStateLeFrntTurnLamp_Flow:
            case NormalStateLeFrntTurnLamp_DayTime:
            case NormalStateLeFrntTurnLamp_DayTimeAndPosBoth_ButDayTime:
            case NormalStateLeFrntTurnLamp_Posn:
            case NormalStateLeFrntTurnLamp_DayTimeAndPosBoth_ButPosn:
            case NormalStateLeFrntTurnLamp_Default:
            {
                SelectExitLogic(normalStateMachine, lastState, newState);
                SelectEntryLogic(normalStateMachine, newState);
                break;
            }

            default:
            {
                SelectEntryLogic(normalStateMachine, newState);
                break;
            }
        }
    }
}

void NormalTurnStateMachineExecuteLogic(NormalStateMachine* normalStateMachine, NormalState lastState, NormalState newState)
{
    NormalStateMachineEntryLogic(normalStateMachine, lastState, newState);
    switch(newState)
    {
        case NormalStateLeFrntTurnLamp_Flicker:
        {
            if(waitLastStateExitFinish(&normalStateMachine->leFrntTurnLampFlicker_.sm_))
            {
                normalStateMachine->leFrntTurnLampFlicker_.sm_.Excute();
            }
            else
            {
                //wait
            }
            break;
        }

        case NormalStateLeFrntTurnLamp_Flow:
        {

            if(waitLastStateExitFinish(&normalStateMachine->leFrntTurnLampFlow_.sm_))
            {
                normalStateMachine->leFrntTurnLampFlow_.sm_.Excute();
            }
            else
            {
                //wait
            }
            break;
        }

        case NormalStateLeFrntTurnLamp_DayTime:
        case NormalStateLeFrntTurnLamp_DayTimeAndPosBoth_ButDayTime:
        {
            if(waitLastStateExitFinish(&normalStateMachine->dayTimeMode_.sm_))
            {
                normalStateMachine->dayTimeMode_.sm_.Excute();
            }
            else
            {
                //wait
            }
            break;
        }

        case NormalStateLeFrntTurnLamp_Posn:
        case NormalStateLeFrntTurnLamp_DayTimeAndPosBoth_ButPosn:
        {
            if(waitLastStateExitFinish(&normalStateMachine->posnMode_.sm_))
            {
                normalStateMachine->posnMode_.sm_.Excute();
            }
            else
            {
                //wait
            }
            break;
        }

        default:
        {
            if(waitLastStateExitFinish(&normalStateMachine->defaultMode_.sm_))
            {
                normalStateMachine->defaultMode_.sm_.Excute();
            }
            else
            {
                //wait
            }
            break;
        }
    }
}

void NormalStateMachineExitLogic(NormalStateMachine* normalStateMachine, NormalState lastState, NormalState newState)
{
    SelectExitLogic(normalStateMachine, lastState, newState);
}

void NormalModeEntry(void)
{
    // std::cout << "NormalModeEntry" << std::endl;
}

void NormalModeExcute(void)
{
    // std::cout << "NormalModeExcute" << std::endl;
    NormalTurnStateMachineExecuteLogic(&g_NormalStateMachine, g_TurnLastState.normalState_, g_TurnNewState.normalState_);
    UpdateNormalState(g_TurnNewState.normalState_, &g_TurnLastState.normalState_);
}

void NormalModeExit(void)
{
    NormalStateMachineExitLogic(&g_NormalStateMachine, g_TurnLastState.normalState_, g_TurnNewState.normalState_);
    // std::cout << "NormalModeExit" << std::endl;
    UpdateNormalState(NormalStateLeFrntTurnLamp_Default, &g_TurnLastState.normalState_);
}

void NormalStateMachineDefaultEntry(void)
{
    // std::cout << "NormalStateMachineDefaultEntry" << std::endl;
}

void NormalStateMachineDefaultExcute(void)
{
    // std::cout << "NormalStateMachineDefaultExcute" << std::endl;
}

void NormalStateMachineDefaultExit(void)
{
    // std::cout << "NormalStateMachineDefaultExit" << std::endl;
}

void NormalStateMachineLeFrntTurnLampFlickerEntry(void)
{
    // std::cout << "NormalStateMachineLeFrntTurnLampFlickerEntry" << std::endl;
}

void NormalStateMachineLeFrntTurnLampFlickerExcute(void)
{
    // std::cout << "NormalStateMachineLeFrntTurnLampFlickerExcute" << std::endl;
    // buildLeTurnLamp_TL_EN_FaultFlag(&g_LeFrntTrunLampView.lastModel_.TL_EN_FaultFlag_, &g_LeFrntTrunLampView.model_->TL_EN_FaultFlag_);  //dev support
    g_LeFrntTrunLampView.model_->onOffStatus_ = OnOff_On;
    g_DayTimeAndPosLampView.model_->onOffStatus_ = OnOff_Invalid;
    playLeFrntTurnLampFlickerAnimation(&g_LeFrntTrunLampView.model_->mask, &g_LeFrntTrunLampView.model_->pwm_);
}

void NormalStateMachineLeFrntTurnLampFlickerExit(void)
{
    // std::cout << "NormalStateMachineLeFrntTurnLampFlickerExit" << std::endl;
    g_LeFrntTrunLampView.model_->onOffStatus_ = OnOff_Invalid;
    trenLeFrntTurnLampOff(&g_LeFrntTrunLampView.model_->mask, &g_LeFrntTrunLampView.model_->pwm_);
}


void NormalStateMachineLeFrntTurnLampFlowEntry(void)
{
    // std::cout << "NormalStateMachineLeFrntTurnLampFlowEntry" << std::endl;
}

void NormalStateMachineLeFrntTurnLampFlowExcute(void)
{
    // std::cout << "NormalStateMachineLeFrntTurnLampFlowExcute" << std::endl;
    // buildLeTurnLamp_TL_EN_FaultFlag(&g_LeFrntTrunLampView.lastModel_.TL_EN_FaultFlag_, &g_LeFrntTrunLampView.model_->TL_EN_FaultFlag_);  //dev support
    g_LeFrntTrunLampView.model_->onOffStatus_ = OnOff_On;
    g_DayTimeAndPosLampView.model_->onOffStatus_ = OnOff_Invalid;
    playLeFrntTurnLampFlowAnimation(&g_LeFrntTrunLampView.model_->mask, &g_LeFrntTrunLampView.model_->pwm_);
}

void NormalStateMachineLeFrntTurnLampFlowExit(void)
{
    // std::cout << "NormalStateMachineLeFrntTurnLampFlowExit" << std::endl;
    g_LeFrntTrunLampView.model_->onOffStatus_ = OnOff_Off;
    trenLeFrntTurnLampOff(&g_LeFrntTrunLampView.model_->mask, &g_LeFrntTrunLampView.model_->pwm_);
}


void NormalStateMachineDayTimeModeEntry(void)
{
    // std::cout << "NormalStateMachineDayTimeModeEntry" << std::endl;
}

void NormalStateMachineDayTimeModeExcute(void)
{
    // std::cout << "NormalStateMachineDayTimeModeExcute" << std::endl;
    g_DayTimeAndPosLampView.model_->onOffStatus_ = OnOff_On;
    g_LeFrntTrunLampView.model_->onOffStatus_ = OnOff_Off;
    g_DayTimeAndPosLampView.model_->mask_ = 0xffffffff;
    g_DayTimeAndPosLampView.model_->pwm_ = DaytimeLampPwm_MaxCurrent;//0.188A
    g_StarrySkyView.model_->onOffStatus_ = OnOff_Off;
    g_StarrySkyView.model_->pwm_ = 0.0;
    g_StarrySkyView.model_->mask_ = 0x0;
}

void NormalStateMachineDayTimeModeExit(void)
{
    // std::cout << "NormalStateMachineDayTimeModeExit" << std::endl;
    g_DayTimeAndPosLampView.model_->onOffStatus_ = OnOff_Off;
    g_LeFrntTrunLampView.model_->onOffStatus_ = OnOff_Off;
    g_DayTimeAndPosLampView.model_->onOffStatus_ = OnOff_Off;
    g_DayTimeAndPosLampView.model_->mask_ = 0.0;
    g_DayTimeAndPosLampView.model_->pwm_ = 0.0f;
}


void NormalStateMachinePosnModeEntry(void)
{
    // std::cout << "NormalStateMachinePosnModeEntry" << std::endl;
}

void NormalStateMachinePosnModeExcute(void)
{
    // std::cout << "NormalStateMachinePosnModeExcute" << std::endl;
    g_DayTimeAndPosLampView.model_->onOffStatus_ = OnOff_On;
    g_LeFrntTrunLampView.model_->onOffStatus_ = OnOff_Off;
    g_DayTimeAndPosLampView.model_->mask_ = 0xffffffff;
    g_DayTimeAndPosLampView.model_->pwm_ = getPosnBriSet();
    g_StarrySkyView.model_->onOffStatus_ = g_DayTimeAndPosLampView.model_->onOffStatus_;
    g_StarrySkyView.model_->pwm_ = getStarrySkyBriSet();
    g_StarrySkyView.model_->mask_ = 0xfffff;
}

void NormalStateMachinePosnModeExit(void)
{
    // std::cout << "NormalStateMachinePosnModeExit" << std::endl;
    g_DayTimeAndPosLampView.model_->onOffStatus_ = OnOff_Off;
    g_LeFrntTrunLampView.model_->onOffStatus_ = OnOff_Off;
    g_DayTimeAndPosLampView.model_->onOffStatus_ = OnOff_Off;
    g_DayTimeAndPosLampView.model_->mask_ = 0x0;
    g_DayTimeAndPosLampView.model_->pwm_ = 0.0f;
    g_StarrySkyView.model_->onOffStatus_ = OnOff_Off;
    g_StarrySkyView.model_->pwm_ = 0.0f;
    g_StarrySkyView.model_->mask_ = 0x0;
}



